
#ifndef _COMM_FRAME_H_
#define _COMM_FRAME_H_

#include "config.h"
#include "comm.h"
#include "crc16.h"

#define COMM_FRAME_BUF_MAX_SIZE (1024 * 1024 * 10) // 10 MByte

typedef struct comm_frame_packet_t
{
#define COMM_FRAME_PACKET_MAX_LEN			(1024 * 40)
#define	COMM_FRAME_PACKET_SOF_LEN			(sizeof(uint8_t) * 4)
#define	COMM_FRAME_PACKET_HEAD_RAW_LEN		(sizeof(uint32_t) + sizeof(int) * 3 + sizeof(uint16_t))
#define COMM_FRAME_PACKET_HEADER_LEN		(COMM_FRAME_PACKET_SOF_LEN + COMM_FRAME_PACKET_HEAD_RAW_LEN)
#define	COMM_FRAME_PACKET_HEAD_NO_CRC_LEN	(COMM_FRAME_PACKET_HEADER_LEN - sizeof(uint16_t))
#define COMM_FRAME_PACKET_SEND_LEN(v)		(v + COMM_FRAME_PACKET_HEADER_LEN)

#define COMM_FRAME_PACKET_SOF "HEAD"
#define COMM_FRAME_PACKET_SOF_1 'H'
#define COMM_FRAME_PACKET_SOF_2 'E'
#define COMM_FRAME_PACKET_SOF_3 'A'
#define COMM_FRAME_PACKET_SOF_4 'D'

	uint8_t sof[4];
	uint32_t seq_no;
	int len_total;
	int len_done;
	int len_now;
	uint16_t crc16;

	uint8_t buf[COMM_FRAME_PACKET_MAX_LEN];
} comm_frame_packet_t;

typedef struct comm_frame_send_context_t
{
	enum COMM_FRAME_SEND_STATE
	{
		COMM_FRAME_SEND_NOT_INIT = 0,
		COMM_FRAME_SEND_READY,
		COMM_FRAME_SEND_BUSY,
	} state;

	sockfd		upd_fd;

	//sockaddr_in	dest_addr;
	//sockaddr_in local_addr;

	struct sockaddr_in	dest_addr;
	struct sockaddr_in	local_addr;

	uint32_t	seq_no;
	
	int			send_buf_valid;
	int			send_len_total;
	int			send_len_now;
	int			send_len_done;

	uint8_t dummpy_1[100];
	comm_frame_packet_t frame_packet;
	uint8_t dummpy_2[100];
} comm_frame_send_context_t;

typedef struct comm_frame_recv_context_t
{
#define COMM_FREAME_RECV_TIMEOUT_MICRO_SECOND 10000

	enum COMM_FRAME_RECV_RAW_STATE
	{
		COMM_FRAME_RECV_RAW_READY = 0,
		COMM_FRAME_RECV_RAW_SOF,
		COMM_FRAME_RECV_RAW_HEADER,
		COMM_FRAME_RECV_RAW_DATA,
	} raw_state;

	enum COMM_FRAME_RECV_STATE
	{
		COMM_FRAME_RECV_NOT_INIT = 0,
		COMM_FRAME_RECV_READY,
		COMM_FRAME_RECV_RECEIVING,
		COMM_FRAME_RECV_COMPLETE,
		COMM_FRAME_RECV_TIMEOUT,
	}state;

	sockfd		upd_fd;
	int			dest_addr_len;

	struct sockaddr_in	dest_addr;
	struct sockaddr_in local_addr;

	uint32_t	recv_seq_no;
	int			recv_len_total;
	int			recv_len_done;
	
	int			raw_len;
	uint32_t	recv_timeout;
	comm_packet_t*    recv_buf;

	uint8_t dummpy_1[100];
	comm_frame_packet_t frame_packet;
	uint8_t dummpy_2[100];
} comm_frame_recv_context_t;

int comm_frame_send(int fd, uint8_t* buf, int len);

#endif /* _COMM_FRAME_H_ */
